home *** CD-ROM | disk | FTP | other *** search
/ A Teacher's Guide to the Holocaust / A Teacher's Guide to the Holocaust.iso / data / people / scripts / interactionclass.js < prev    next >
Text File  |  1999-12-05  |  19KB  |  568 lines

  1. // Copyright 1998,1999 Macromedia, Inc. All rights reserved.
  2.  
  3. // Localization strings
  4. var TRACK_system_not_found = "Tracking system not found.";
  5.  
  6. //Constructs an Interaction
  7. function MM_interaction(theSelf,
  8.                theJudgeOnSel, theAllowMultiSel, theAllThatApply, theUnknownIsCorrect,
  9.                theDisabled, theTriesLimit, theTimeLimit,
  10.                theTrackIntId, theTrackObjectiveId,
  11.                theTrackQType,theTrackWeight, theKTrack) {
  12.   // properties
  13.   this.judgeOnSel = theJudgeOnSel;
  14.   this.allowMultiSel = theAllowMultiSel;
  15.   this.allThatApply = theAllThatApply;
  16.   this.unknownIsCorrect = theUnknownIsCorrect;
  17.   this.disabled = theDisabled;
  18.   this.tries = 0;
  19.   this.triesLimit = (theTriesLimit)?theTriesLimit:0;
  20.   this.triesAtLimit = false;
  21.   this.time = 0;
  22.   this.timeLeft = 0;
  23.   this.timeLimit = (theTimeLimit)?theTimeLimit:0;
  24.   this.timeAtLimit = false;
  25.   this.trackIntId = theTrackIntId;
  26.   this.trackObjectiveId = theTrackObjectiveId;
  27.   this.trackQType = theTrackQType;
  28.   this.trackWeight = theTrackWeight;
  29.   this.knowledgeTrack = theKTrack;
  30.   this.totalElems = 0;
  31.   this.possCorrect = 0;
  32.   this.possIncorrect = 0;
  33.   this.knownResponse = false;
  34.   this.totalCorrect = 0;
  35.   this.totalIncorrect = 0;
  36.   this.correct = false;
  37.   this.score = 0;
  38.  
  39.   this._self = theSelf;
  40.   this._timeStart = 0;
  41.   this._timerID = 0;
  42.   
  43.   this.browserIsNS = (navigator.appName.indexOf('Netscape') != -1);
  44.   this.browserIsIE = (navigator.appName.indexOf('Microsoft') != -1);
  45.   this.osIsWindows = (navigator.appVersion.indexOf('Win') != -1);
  46.   this.osIsMac = (navigator.appVersion.indexOf('Mac') != -1); // ????
  47.   this.browserVersion = parseFloat(navigator.appVersion);
  48.   
  49.   this.e = new Array();
  50.   this.b = new Array();
  51.  
  52.   // methods
  53.   this.init = MM_intInit;
  54.   this.reset = MM_intReset;
  55.   this.resetElems = MM_intResetElems;
  56.   this.enable = MM_intEnable;
  57.   this.disable = MM_intDisable;
  58.   this.setDisabled = MM_intSetDisabled;
  59.   this.update = MM_intUpdate;
  60.   this.add = MM_intAdd;
  61.   this.setTries = MM_intSetTries;
  62.   this.setTriesLimit = MM_intSetTriesLimit;
  63.   this.setTime = MM_intSetTime;
  64.   this.setTimeLimit = MM_intSetTimeLimit;
  65.   this.track = MM_intTrack
  66.   this.getTime = MM_intGetTime;
  67.  
  68.   this.am = MM_intAm;
  69.   this.judge = MM_intJudge;
  70.   this.resetActionMgr = MM_intResetActionMgr;
  71.   this.setSegmNode = MM_intSetSegmNode;
  72.   this.getSegmNode = MM_intGetSegmNode;
  73.   this.setSegmDisabled = MM_intSetSegmDisabled;
  74.   this.getSegmDisabled = MM_intGetSegmDisabled;
  75. }
  76.  
  77. //Calls the element init funtions if they exist, and then does a reset
  78. function MM_intInit() {
  79.   var i,j,localPC;
  80.  
  81.   with (this) {
  82.     // init elems, and set totalElems, possCorrect, possIncorrect;
  83.     totalElems = 0;
  84.     possCorrect = 0;
  85.     possIncorrect = 0;
  86.     for (i in e) if (i != 'length') {
  87.       if (e[i].init != null) e[i].init();
  88.       totalElems++;
  89.       localPC = 0;
  90.       for (j in e[i].c) if (j != 'length' && e[i].c[j].isCorrect != null)
  91.         (e[i].c[j].isCorrect) ? localPC++ : possIncorrect++;
  92.       if (e[i]._singleChoice != null && localPC > 1)
  93.         localPC = 1;
  94.       possCorrect += localPC;
  95.     }
  96.     reset();
  97.     if (knowledgeTrack) {
  98.       var frm = findcmiframe(null);
  99.       if (frm == null) {
  100.         installcmi(window); //layers in NS
  101.         if (!CMIIsPresent()) {
  102.           var cmi = cmiinit(window);
  103.           if (cmi) CMIInitialize();
  104.           else if (!window.trackwarning) {
  105.             alert(TRACK_system_not_found);
  106.             window.trackwarning = true;
  107.       } } } 
  108.       else {
  109.         if (window.CMIInitialize == null) frm.installcmi(window);
  110.         if (window.CMIInitialize != null) CMIInitialize();
  111.         if (!CMIIsPresent() && !window.trackwarnings) {
  112.           alert(TRACK_system_not_found);
  113.           window.trackwarning = true;
  114.   } } } }
  115.   window["'"+this._self+"'"] = this._self; //redeclare global on window in case inserted in layer
  116. }
  117.  
  118. //Called to reset the interaction
  119. function MM_intReset() {
  120.   with (this) {
  121.     tries = 0;
  122.     triesAtLimit = false;
  123.     _timeStart = Math.floor((new Date()).getTime()/1000);
  124.     if (_timerID) clearTimeout(_timerID);
  125.     if (!disabled && timeLimit) _timerID = setTimeout(_self+".judge()",(timeLimit+1)*1000);
  126.     time = 0;
  127.     timeLeft = timeLimit;
  128.     timeAtLimit = false;
  129.   
  130.     resetActionMgr();
  131.     resetElems();
  132.     update(true);
  133.   }
  134. }
  135.  
  136. //Calls the reset for the individual elements
  137. function MM_intResetElems() {
  138.   with (this) {
  139.     for (var i in e) if (i != 'length')
  140.       if (e[i].reset != null)  e[i].reset();
  141.     update(true);
  142.   }
  143. }
  144.  
  145. //Enables the interaction
  146. function MM_intEnable() {
  147.   if (this.disabled) with (this) {
  148.     _timeStart = Math.floor((new Date()).getTime()/1000) - time;
  149.     if (timeLimit)
  150.       _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);
  151.     disabled = false;
  152.     update(true);
  153.     for (var i in e) if (i != 'length')
  154.       if (e[i].enable != null)  e[i].enable();
  155.   }
  156. }
  157.  
  158. //Disables the interaction
  159. function MM_intDisable() {
  160.   if (!this.disabled) with (this) {
  161.     update(true);  // update 'time'
  162.     if (_timerID) clearTimeout(_timerID);  // clear the timer
  163.     disabled = true;
  164.     for (var i in e) if (i != 'length')
  165.       if (e[i].disable != null)  e[i].disable();
  166.   }
  167. }
  168.  
  169. //Calls the approppriate disable or enable function
  170. function MM_intSetDisabled(theDisabled) {
  171.   if (theDisabled) this.disable();
  172.   else this.enable();
  173. }
  174.  
  175. //Update the interaction state
  176. // Note: tries will be updated by the judge method, and time will
  177. //       be updated by both this method and the judge method.
  178. function MM_intUpdate(noJudge) {
  179.   if (!this.disabled) with (this) {
  180.     knownResponse = false;
  181.     totalCorrect = 0;
  182.     totalIncorrect = 0;
  183.     correct = false;
  184.     score = 0;
  185.     for (var i in e) if (i != 'length') {
  186.       for (var j in e[i].c) if (j != 'length') {
  187.         if (e[i].c[j].selected) {
  188.           knownResponse = true;
  189.           score += e[i].c[j].score;
  190.           if (e[i].c[j].isCorrect != null)
  191.             (e[i].c[j].isCorrect) ? totalCorrect++ : totalIncorrect++;
  192.     } } }
  193.     if (!knownResponse) correct = unknownIsCorrect;
  194.     else if (totalIncorrect != 0) correct = false;
  195.     else if (totalCorrect == 0) correct = null; // not judged
  196.     else correct = (!allThatApply || totalCorrect >= possCorrect);
  197.   
  198.     time = Math.floor((new Date()).getTime()/1000) - _timeStart;
  199.     if (timeLimit && !timeAtLimit) {
  200.       timeLeft = Math.max(0, timeLimit - time);
  201.       timeAtLimit = (time > timeLimit);
  202.     }
  203.   
  204.     if (judgeOnSel && !noJudge)  judge();
  205.   }
  206. }
  207.  
  208. function MM_intSetTries(theTries) {
  209.   with (this) {
  210.     tries = theTries;
  211.     triesAtLimit = (triesLimit) ? (tries >= triesLimit) : false;
  212.   }
  213. }
  214.  
  215. function MM_intSetTriesLimit(theTriesLimit) {
  216.   with (this) {
  217.     triesLimit = theTriesLimit;
  218.     triesAtLimit = (triesLimit) ? (tries >= triesLimit) : false;
  219.   }
  220. }
  221.  
  222. function MM_intSetTime(theTime) {
  223.   with (this) {
  224.     time = Math.max(0, theTime);
  225.     _timeStart = Math.floor((new Date()).getTime()/1000) - time;
  226.     timeLeft = (timeLimit) ? Math.max(0, timeLimit - time) : timeLimit;
  227.     timeAtLimit = (timeLimit) ? (time > timeLimit) : false;
  228.     if (_timerID) clearTimeout(_timerID);  // clear the timer
  229.     if (!disabled && timeLimit)
  230.       _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);
  231.   }
  232. }
  233.  
  234. function MM_intSetTimeLimit(theTimeLimit) {
  235.   with (this) {
  236.     if (!disabled)
  237.       time = Math.floor((new Date()).getTime()/1000) - _timeStart;
  238.     timeLimit = theTimeLimit;
  239.     timeLeft = (timeLimit) ? Math.max(0, timeLimit - time) : timeLimit;
  240.     timeAtLimit = (timeLimit) ? (time > timeLimit) : false;
  241.     if (_timerID) clearTimeout(_timerID);  // clear the timer
  242.     if (!disabled && timeLimit)
  243.       _timerID = setTimeout(_self+".judge()",Math.max(0,(timeLimit-time)+1)*1000);
  244.   }
  245. }
  246.  
  247. function MM_intAdd(theType, A, B, C, D, E, F, G, H, I, J, K, L, M) {
  248.   var theObj = eval("new MM_" + theType + "(" + this._self + ", A, B, C, D, E, F, G, H, I, J, K, L, M)");
  249.   if (theObj._isChoice != null)
  250.     this.e[A].c[B] = theObj;
  251.   else
  252.     this.e[A] = theObj;
  253. }
  254.  
  255. function MM_intTrack() {
  256.   var  aDt= new Date();
  257.   var curHr=aDt.getHours()+'', curMin=aDt.getMinutes()+'', curSec=aDt.getSeconds()+'';
  258.   var curDay=aDt.getDate()+'', curMonth=aDt.getMonth()+1+'', curYear=aDt.getYear(), dmy;
  259.   var lat = Math.floor(aDt.getTime()/1000) - this._timeStart;
  260.   var x=3600;
  261.   var y=60;
  262.   var hrs=Math.round(lat/x - lat%x/x)+'';
  263.   var min=Math.round((lat-hrs*x)/y-(lat-hrs*x)%y/y)+'';
  264.   var sec=Math.round(lat-hrs*x-min*y)+'';
  265.   var sRes,cRes,res,aName,bName,isC,isNC,isSel,iType;
  266.  
  267.   if (curYear < 1900) curYear += 1900;
  268.   if (curDay.toString().length==1) curDay = '0'+curDay;
  269.   if (curMonth.toString().length==1) curMonth = '0'+curMonth;
  270.   dmy = curDay+"/"+curMonth+"/"+curYear;
  271.   
  272.   sRes=cRes=res=aName=bName=""
  273.  
  274.   with (this) {  
  275.     if (trackQType.length==0) return;
  276.     iType=trackQType.charAt(0).toLowerCase();
  277.     if (allThatApply&&possCorrect>1) sRes=cRes='{';
  278.     
  279.     for (var i in e) if (i != 'length') {
  280.       for (var j in e[i].c) if (j != 'length') {
  281.         isC=e[i].c[j].isCorrect;
  282.         isSel=e[i].c[j].selected;
  283.         if (iType=='m') {
  284.           aName=e[i].c[j]._elem._name;
  285.           bName=e[i].c[j]._target._name;
  286.           if (isC) cRes+=aName+'.'+bName+',';
  287.           if (isSel) sRes+=aName+'.'+bName+',';
  288.         }
  289.         else if (iType=='f') {
  290.           aName=e[i].value;
  291.           bName=MM_textDeencrypt(e[i].c[j].expectedValue);
  292.           if (isC) cRes+=bName+',';
  293.           if (isSel) sRes+=aName+',';
  294.         }
  295.         else if ((iType=='c')||(iType=='t')) {
  296.           if (e[i]._trkObj!=null) {
  297.             aName=e[i].c[j].expectedValue;
  298.             x=aName.indexOf(':');
  299.             aName=aName.substring(0,x)+'-'+aName.substring(x+1,aName.length)
  300.             bName=e[i].value
  301.           }
  302.           else if (e[i]._tick!=null) {
  303.             aName=e[i].c[j].expectedValue;
  304.             if (isSel) bName = aName;
  305.           }
  306.           else if (e[i]._stateMask!=null && totalElems==1) {
  307.             aName=e[i].expectedValue;
  308.             bName=e[i].value;
  309.           }
  310.           else
  311.             aName=bName=e[i].c[j]._name;
  312.  
  313.           if (isC) cRes+=aName+',';
  314.           if (isSel) sRes+=bName+',';
  315.         }
  316.         else {
  317.           aName=bName='';
  318.           if (isC) cRes+=',';
  319.           if (isSel) sRes+=',';
  320.         }
  321.  
  322.         isNC=(isC==false)&&isSel;
  323.         isC=isC&&isSel;
  324.         if (possCorrect>1)  res=res+(isC?'c,':isNC?'w,':isSel?'n,':'');
  325.         else if (isSel) res = isC?'c':isNC?'w':'n';
  326.       }
  327.     }
  328.     
  329.     if (sRes.charAt(sRes.length-1)==',') sRes=sRes.substring(0,sRes.length-1);
  330.     if (cRes.charAt(cRes.length-1)==',') cRes=cRes.substring(0,cRes.length-1);
  331.     if (res.charAt(res.length-1)==',') res=res.substring(0,res.length-1);
  332.     if (allThatApply&&possCorrect>1) {
  333.       sRes=sRes+'}';
  334.       cRes=cRes+'}';
  335.     }
  336.     if (window.CMIIsPresent && CMIIsPresent()) {
  337.       if (hrs.toString().length==1) hrs = '0'+hrs;
  338.       if (min.toString().length==1) min = '0'+min;
  339.       if (sec.toString().length==1) sec = '0'+sec;
  340.       if (curHr.toString().length==1) curHr = '0'+curHr;
  341.       if (curMin.toString().length==1) curMin = '0'+curMin;
  342.       if (curSec.toString().length==1) curSec = '0'+curSec;
  343.       CMIAddInteraction(dmy, curHr+":"+curMin+":"+curSec, 
  344.        trackIntId, trackObjectiveId, trackQType, 
  345.        cRes, sRes, res, trackWeight, hrs+":"+min+":"+sec);
  346.     }
  347.   }  
  348. }
  349.  
  350.  
  351. function MM_intGetTime() { 
  352.   var date = new Date();
  353.   this.time = (date.getTime()/1000 - this._timeStart)*1000;
  354.   return this.time/1000;
  355. }
  356.  
  357.  
  358. //Finds any object in either browser using recursion.
  359. //Only pass the first argument, the name of the object to find.
  360. //Returns a pointer the object if found, else an empty string.
  361. //  MM_intFindObject('bar') returns the object
  362. //  document.layers['foo'].document.layers['bar']
  363.  
  364. function MM_intFindObject(objName,  parentObj) {
  365.   var i,tempObj="",found=false,curObj = "";
  366.   var NS = (navigator.appName.indexOf("Netscape") != -1);
  367.   if (!NS && document.all) curObj = document.all[objName]; //IE4
  368.   if (!curObj) {
  369.     parentObj = (parentObj != null)? parentObj.document : document;
  370.     if (parentObj[objName] != null) curObj = parentObj[objName]; //at top level
  371.     else { //if in form
  372.       if (parentObj.forms) for (i=0; i<parentObj.forms.length; i++) {  //search level for form object
  373.         if (parentObj.forms[i][objName]) {
  374.           curObj = parentObj.forms[i][objName];
  375.           found = true; break;
  376.       } }
  377.       if (!found && NS && parentObj.layers && parentObj.layers.length > 0) {
  378.         parentObj = parentObj.layers;
  379.         for (i=0; i<parentObj.length; i++) { //else search for child layers
  380.           tempObj = MM_intFindObject(objName,parentObj[i]); //recurse
  381.           if (tempObj) { curObj = tempObj; break;} //if found, done
  382.   } } } }
  383.   return curObj;
  384. }
  385.  
  386. //Called from within conditions to check document properties
  387. function MM_getDocProp(theName, theProp, theType) {
  388.   var theObj = MM_intFindObject(theName);
  389.   if (theObj) return eval('theObj.' + theProp);
  390.   else return null;
  391. }
  392.  
  393.  
  394. //*********  ACTION MGR METHODS  *********
  395.  
  396. function MM_intJudge(treeRoot,curRoot,level) {
  397.   var i=0,theNode,retVal=true,firstCond = true;
  398.   level = (curRoot == null)?0:level+1;
  399.   if (!level) {
  400.     curRoot = this; //set tree to highest level
  401.     if (this.disabled) retVal=false;
  402.     else {
  403.       this.time = Math.floor((new Date()).getTime()/1000) - this._timeStart;
  404.       if (this.timeLimit && !this.timeAtLimit) {
  405.         this.timeLeft = Math.max(0, this.timeLimit - this.time);
  406.         this.timeAtLimit = (this.time > this.timeLimit);
  407.       }
  408.       this.tries++;
  409.       if (this.triesLimit)
  410.         this.triesAtLimit = (this.tries >= this.triesLimit);
  411.   } } else if (treeRoot.curNode != null && curRoot == treeRoot.curNode) //if at curNode
  412.     i = treeRoot.curIndex;  //offset by index
  413.   for (i; (retVal && i<curRoot.b.length); i++) {
  414.     theNode = curRoot.b[i];
  415.     if (this.disabled) retVal=false;
  416.     else if (theNode.disabled) continue;
  417.     else if (theNode.type == "segm") { //SEGMENT
  418.       curNode = (theNode.curNode)?theNode.curNode:theNode;
  419.       if (curNode != 'done')
  420.         retVal = MM_intJudge(theNode,curNode,level);   //start from that node
  421.       else if (!level) continue;
  422.     } else if (theNode.type == 'cond') { //CONDITION
  423.       if (eval(theNode.data)) {
  424.         if (!treeRoot.data) treeRoot.curNode = 'done';  //if not "auto-reset tree", set curNode
  425.         retVal = MM_intJudge(treeRoot,theNode,level);
  426.         if (level) break;
  427.       } else if (firstCond) {
  428.         firstCond = false;
  429.         if (!treeRoot.data) {treeRoot.curNode = curRoot;  treeRoot.curIndex = i;}
  430.       }
  431.     } else if (theNode.type == 'actn') { //ACTION
  432.       if (!treeRoot.data) //not auto-reset
  433.         if (i<(curRoot.b.length-1)) { //not last node
  434.           treeRoot.curNode = curRoot;  treeRoot.curIndex = i+1; //set curNode to next node
  435.         } else treeRoot.curNode = 'done'; //last node, clear curNode
  436.       if (theNode.data == 'stop') retVal=false; //STOP
  437.       else eval(theNode.data);
  438.   } }
  439.   if (!level && curRoot!=null && curRoot.knowledgeTrack) curRoot.track();
  440.   return retVal
  441. }
  442.  
  443.  
  444. //Disables or enables ActionMgr segments. If no segment passed,
  445. //disables *all* segments. Returns false if segment not found.
  446.  
  447. function MM_intSetSegmDisabled(segmName,disable) {
  448.   var i, retVal=false;
  449.   for (i=0; i<this.b.length; i++) //search for segment
  450.     if (!segmName || this.b[i].name==segmName) {
  451.       this.b[i].disabled=disable; retVal = true;
  452.       if (segmName) break;
  453.     }
  454.   return retVal
  455. }
  456.  
  457.  
  458. //Returns the disabled flag from an ActionMgr segment.
  459. //Returns null if segment not found.
  460.  
  461. function MM_intGetSegmDisabled(segmName) {
  462.   var i, retVal=null;
  463.   for (i=0; i<this.b.length; i++) //search for segment
  464.     if (this.b[i].name==segmName) {
  465.       retVal = this.b[i].disabled; break;
  466.     }
  467.   return retVal
  468. }
  469.  
  470.  
  471. function MM_intResetActionMgr(segmName) {
  472.   var i;
  473.   if (segmName != null) MM_intTreeSetCurNode(segmName,null,this); //clear single curNode
  474.   else for (i=0;i<this.b.length;i++) this.b[i].curNode = null; //clear all curNodes
  475. }
  476.  
  477.  
  478. function MM_intSetSegmNode(segmName,condName) {
  479.   var i, curRoot=null;
  480.   if (!condName) this.resetActionMgr(segmName);
  481.   else {
  482.     for (i=0; i<this.b.length; i++) //search for segment, set as curRoot
  483.       if (this.b[i].name == segmName) { curRoot = this.b[i]; break; }
  484.     MM_intTreeSetCurNode(condName,null,curRoot,curRoot);
  485.   }
  486. }
  487.  
  488.  
  489. function MM_intTreeSetCurNode(nodeName,newVal,treeRoot,curRoot) {
  490.   var i,theNode;
  491.   if (curRoot==null) curRoot = treeRoot; //if first time, use treeRoot
  492.   for (i=0; i<curRoot.b.length; i++) {
  493.     theNode = curRoot.b[i];
  494.     if (theNode.type == "segm") { //SEGMENT
  495.       if (theNode.name == nodeName) theNode.curNode  = newVal;
  496.       else MM_intTreeSetCurNode(nodeName,newVal,theNode,theNode);
  497.     } else if (theNode.type == 'cond') { //CONDITION
  498.       if (theNode.name == nodeName) {  //if name found
  499.         treeRoot.curNode = curRoot;  treeRoot.curIndex = i;
  500.         break;
  501.       } else MM_intTreeSetCurNode(nodeName,newVal,treeRoot,theNode);
  502.   } }
  503. }
  504.  
  505.  
  506. //Returns the current node for the given Segment, returned as:
  507. // top of segment    - "" (empty string)
  508. // middle of segment - condition name
  509. // end of segment    - "done"
  510.  
  511. function MM_intGetSegmNode(segmName) {
  512.   var i, curNode='';
  513.   for (i=0; i<this.b.length; i++) //search for segment
  514.     if (this.b[i].name == segmName) { 
  515.       curNode = this.b[i].curNode;
  516.       if (curNode==null) curNode = "";
  517.       else if (curNode!="done") curNode = curNode.b[this.b[i].curIndex].name;
  518.       break; 
  519.     }
  520.   return curNode
  521. }
  522.  
  523.  
  524.  
  525. //*********  ACTION MGR NODE CLASS  *********
  526.  
  527. function MM_intNode(theType,theName,theData) {
  528.   this.type = (theType)?theType:'';
  529.   this.name = (theName)?theName:'';
  530.   this.data = (theData)?theData:'';
  531.   this.b = new Array();
  532. }
  533.  
  534.  
  535. //Create Action Manager (tree)
  536.  
  537. function MM_intAm(theType,theName,theData) {
  538.   if (theType == "segm") {
  539.       if (!this.tParent) { //initialize system
  540.         this.tParent = new Array(); //tree parent nodes
  541.         this.tIndex = new Array();  //child indexes
  542.         this.tIndex[0] = -1;        //set index for root depth
  543.       }
  544.       this.tLevel = 0;            //reset level to 0
  545.       this.tIndex[this.tLevel]++; //increment the index
  546.       this.b[this.tIndex[this.tLevel]] = new MM_intNode("segm", theName,theData); //create tree
  547.       this.tParent[this.tLevel] = this.b[this.tIndex[this.tLevel]]; //put this tree root at top level
  548.       this.tIndex[this.tLevel+1] = -1;                              //reset child level index
  549.  
  550.   } else if (theType == "actn") {
  551.      var parentNode = this.tParent[this.tLevel];    //get parent
  552.      var levelIndex = ++this.tIndex[this.tLevel+1]; //get index
  553.      parentNode.b[levelIndex] = new MM_intNode('actn',theName,theData); //add action
  554.  
  555.   } else if (theType == "cond") {
  556.      var parentNode = this.tParent[this.tLevel];    //get parent
  557.      var levelIndex = ++this.tIndex[this.tLevel+1]; //get index
  558.      parentNode.b[levelIndex] = new MM_intNode('cond',theName,theData); //add condition
  559.  
  560.      this.tLevel++; //go down a level
  561.      this.tParent[this.tLevel] = parentNode.b[levelIndex]; //save this node as parent
  562.      this.tIndex[this.tLevel+1] = -1;                      //reset child level index
  563.  
  564.   } else if (theType == "end") {
  565.      this.tLevel--;  //go up a level
  566.   }
  567. }
  568.